package com.dsg.workflow;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.common.util.FileNotCompleteException;
import com.dsg.common.util.SingletonLoginUtils;
import com.dsg.common.util.UUIDGenerator;
import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.common.util.toolbox.StringUtil;
import com.dsg.entity.apply.DsgApplyBill;
import com.dsg.entity.apply.DsgApplyCar;
import com.dsg.entity.apply.DsgApplyPay;
import com.dsg.entity.approve.DsgApproveCase;
import com.dsg.entity.system.DsgSysFile;
import com.dsg.service.AppContextHolder;
import com.dsg.service.apply.IDsgApplyBillService;
import com.dsg.service.apply.IDsgApplyCarService;
import com.dsg.service.apply.IDsgApplyCusService;
import com.dsg.service.apply.IDsgApplyPayService;
import com.dsg.service.approve.IDsgApproveCaseService;
import com.dsg.service.approve.IDsgApproveTaskService;
import com.dsg.service.system.IDsgSysFileService;
import com.dsg.util.SpringContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class WorkflowEngine {
    @Autowired
    IDsgApproveCaseService caseService;
    @Autowired
    IDsgApplyBillService billService;
    @Autowired
    IDsgApproveTaskService taskService;
    @Autowired
    AppContextHolder contextHolder;
    @Autowired
    IDsgApplyCarService carService;
    @Autowired
    IDsgApplyPayService payService;
    @Autowired
    IDsgApplyCusService cusService;
    @Autowired
    IDsgSysFileService fileService;

    private AbstractWorkflowService get(DsgApproveCase approveCase) throws Exception {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("OID", approveCase.getOid());
        int count = caseService.count(wrapper);
        if (count == 0) {
            throw new Exception("已由別人審批");
        }

        wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", approveCase.getAppNo());
        DsgApplyBill bill = billService.getOne(wrapper);
        AbstractWorkflowService service = (AbstractWorkflowService) SpringContextUtils.getBean("workflowService" + bill.getAppType());
        return service;
    }

    /**
     * 生成上級審批CASE
     * @param nodeName
     * @param bill
     */
    public void genSupApproveCase(String nodeName, DsgApplyBill bill) throws Exception {
        AbstractWorkflowService service = (AbstractWorkflowService) SpringContextUtils.getBean("workflowService" + bill.getAppType());
        service.genByNodeName(nodeName, bill);
    }

    public void forward(DsgApproveCase approveCase) throws Exception {
        get(approveCase).forward(approveCase);
    }

    public void backward(DsgApproveCase approveCase) throws Exception {
        get(approveCase).backward(approveCase);
    }

    public void begin(DsgApplyBill bill) throws Exception {
        AbstractWorkflowService service = (AbstractWorkflowService) SpringContextUtils.getBean("workflowService" + bill.getAppType());
        service.begin(bill);
    }

    /**
     * 改變付款資料就重新過一元
     */
    public void generateDeduOneCases(DsgApplyBill bill) throws Exception {
        AbstractWorkflowService service = (AbstractWorkflowService) SpringContextUtils.getBean("workflowService" + bill.getAppType());
        service.generateDeduOneCases(bill);
    }

    /**
     * 转交跟进
     * @param appNo
     * @param userOid
     */
    @Transactional(rollbackFor = Exception.class)
    public void transmit(String appNo, String userOid) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", appNo);
        SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
        wrapper.eq("USER_ID", sysUser.getUserId());
        wrapper.eq("STATUS", DsgApproveCase.Status.started.getCode());
        DsgApproveCase approveCase = caseService.getOne(wrapper);
        approveCase.setStatus(DsgApproveCase.Status.assigned.getCode());
        caseService.updateById(approveCase);

        approveCase.setOid(UUIDGenerator.getUUID());
        approveCase.setUserId(userOid);
        approveCase.setStatus(DsgApproveCase.Status.started.getCode());
        caseService.save(approveCase);
    }

    /**
     * 文件是否齊全
     * @param approveCase
     * @return
     */
    public void fileComplete(DsgApproveCase approveCase) throws FileNotCompleteException {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", approveCase.getAppNo());
        DsgApplyBill bill = billService.getOne(wrapper, false);

        if (DsgApplyBill.APP_TYPE_3 == bill.getAppType()) {
            wrapper = new QueryWrapper();
            wrapper.eq("MAIN_NO", bill.getMainNo());
            DsgApplyPay pay = payService.getById(bill.getPayId());
            if (pay == null)
                throw new FileNotCompleteException("付款資料");

            wrapper = new QueryWrapper();
            wrapper.eq("APP_NO", approveCase.getAppNo());
            wrapper.eq("ENCL_TYPE", DsgSysFile.ENCL_TYPE_4);
            if (fileService.count(wrapper) == 0) {
                throw new FileNotCompleteException("缺少申請表");
            }

            wrapper = new QueryWrapper();
            wrapper.eq("REL_ID", pay.getOid());
            int payMode = pay.getPayMode();
            if (payMode == DsgApplyPay.PAY_MODE_CDC && pay.getPayer().equals(DsgApplyPay.PAYER_OTHER)) {
                wrapper.eq("ENCL_TYPE", DsgSysFile.ENCL_TYPE_12);
                if (fileService.count(wrapper) == 0) {
                    throw new FileNotCompleteException(String.format("付款資料 %s 缺少第三者信用卡授權書", pay.getPayAccountNo()));
                }

                wrapper = new QueryWrapper();
                wrapper.eq("REL_ID", pay.getOid());
                wrapper.eq("ENCL_TYPE", DsgSysFile.ENCL_TYPE_13);
                if (fileService.count(wrapper) == 0) {
                    throw new FileNotCompleteException(String.format("付款資料 %s 缺少持有人身份證/BR", pay.getPayAccountNo()));
                }
            } else if (payMode == DsgApplyPay.PAY_MODE_DAY_ATP
                    || payMode == DsgApplyPay.PAY_MODE_WEEK_ATP
                    || payMode == DsgApplyPay.PAY_MODE_HALF_MONTH_ATP
                    || payMode == DsgApplyPay.PAY_MODE_MONTH_ATP) {
                wrapper.eq("ENCL_TYPE", DsgSysFile.ENCL_TYPE_14);
                int count = fileService.count(wrapper);
                System.out.println(count);
                System.out.println(fileService.count(new QueryWrapper<>()));
                if (count == 0) {
                    throw new FileNotCompleteException(String.format("付款資料 %s 缺少直接付款授權書", pay.getPayAccountNo()));
                }
            }
        }

        if (DsgApplyBill.APP_TYPE_3 == bill.getAppType() ||
                DsgApplyBill.APP_TYPE_4 == bill.getAppType() ||
                DsgApplyBill.APP_TYPE_7 == bill.getAppType() ||
                DsgApplyBill.APP_TYPE_19 == bill.getAppType()) {
            wrapper = new QueryWrapper();
            wrapper.eq("APP_NO", approveCase.getAppNo());
            List<DsgApplyCar> carList = carService.list(wrapper);
            if (CollectionUtil.isEmpty(carList)) {
                throw new FileNotCompleteException("沒有車資料");
            }
            for (DsgApplyCar car : carList) {
                if (StringUtil.isEmpty(car.getCarNo())) {
                    throw new FileNotCompleteException("車牌號碼不能為空");
                }
                boolean complete = billService.carFileComplete(car.getOid());
                if (!complete) {
                    throw new FileNotCompleteException(String.format("車(%s)附件未齊全", car.getCarNo()));
                }
            }
        }
    }

    /**
     * 重新運算生成CASE
     */
    public void recalculate(DsgApplyBill bill) throws Exception {
        AbstractWorkflowService service = (AbstractWorkflowService) SpringContextUtils.getBean("workflowService" + bill.getAppType());
        service.recalculate(bill);
    }
}
